package zoe.app.start.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.IdUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @author zoe.Zhang
 * @date 2022/12/29
 * @description
 */
@Service
@Slf4j
public class AsyncService {

    @Autowired
    @Lazy
    private AsyncService asyncService;

    public String syncMethod() {
        System.out.println("service");
        return IdUtil.fastSimpleUUID();
    }

    public String thisCallAsync() {
        System.out.println(this);// AsyncService对象本身
        return this.asyncMethod();
    }

    public String aopCallAsync() {
        AsyncService asyncService = (AsyncService) AopContext.currentProxy(); // AsyncService的aop 代理对象
        return asyncService.asyncMethod();
    }

    // 指定线程池
    @Async("zoeTaskScheduler")
    public String asyncMethod() {
        System.out.println(Thread.currentThread().getName());
        ThreadUtil.sleep(3 * 1000); // 线程睡眠 3 秒
        return IdUtil.fastSimpleUUID();
    }

    public String syncMethodBatchBad() throws InterruptedException, ExecutionException {
        TimeInterval timer = DateUtil.timer();
        timer.start();
        /*同步写法，每次get都会等待10S*/
        String str = asyncService.method1("I").get();
        String str2 = asyncService.method2("love").get();
        String str3 = asyncService.method3("async").get();
        long l = timer.intervalSecond();
        log.info("耗时 ==> {}", l);
        return str + str2 + str3;
    }

    public String syncMethodBatchGood() throws InterruptedException, ExecutionException {
        /*异步写法，这边执行时长，取决于调用的方法的最大耗时数*/
        TimeInterval timer = DateUtil.timer();
        timer.start();
        Future<String> futureStr = asyncService.method1("I");
        Future<String> futureStr2 = asyncService.method2("love");
        Future<String> futureStr3 = asyncService.method3("async");
        String str = futureStr.get();
        String str2 = futureStr2.get();
        String str3 = futureStr3.get();
        long l = timer.intervalSecond();
        log.info("耗时 ==> {}", l);
        return str + str2 + str3;
    }

    @Async
    public Future<String> method1(String str) throws InterruptedException {
        Thread.sleep(1000 * 10);
        return new AsyncResult<>(str);
    }

    @Async
    public Future<String> method2(String str) throws InterruptedException {
        Thread.sleep(1000 * 5);
        return new AsyncResult<>(str);
    }

    @Async
    public Future<String> method3(String str) throws InterruptedException {
        Thread.sleep(1000 * 15);
        return new AsyncResult<>(str);
    }
}
